<?php

namespace App\Services;

use App\Models\Company;
use App\Models\CompanyUser;
use App\Models\Department;
use App\Models\DepartmentUser;
use App\Models\PartCompany;
use App\Models\PartCompanyUser;
use App\Models\Project;
use App\Models\User;
use App\Models\ProjectUser;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use PHPUnit\Util\Exception;

class OrganizeService extends BaseService
{
    public $departmentService;
    public $projectService;
    public $partCompanyService;
    public $companyService;

    public function __construct(DepartmentService $departmentService,
                                ProjectService $projectService,
                                PartCompanyService $partCompanyService,
                                CompanyService $companyService)
    {
        parent::__construct();
        $this->departmentService  = $departmentService;
        $this->projectService     = $projectService;
        $this->partCompanyService = $partCompanyService;
        $this->companyService     = $companyService;
    }

    /**
     * 删除组织架构节点，解除用户关系
     */
    public function delNode($type, $id)
    {
        switch ($type) {
            case 'project':
                $instance = Project::query();
                ProjectUser::query()->where('project_id', $id)->delete();
                break;
            case 'part_company':
                $instance = PartCompany::query();
                PartCompanyUser::query()->where('part_company_id', $id)->delete();
                break;
            default:
                $instance = Department::query();
                DepartmentUser::query()->where('department_id', $id)->delete();
        }
        $instance->where('id', $id)->delete();
    }

    /**
     * 返回组织架构
     *
     * @return array
     * @author: lxk
     * @date: 2024/3/19 13:58
     */
    public function organize(): array
    {
        $companyId = company_id();
        $companies = Company::with([
            'departments',
            'projects.departments',
            'projects.partCompanies.departments',
        ])->where('id', $companyId)->select(['id', 'title', 'certificate', 'status'])->get();

        if ($companies->isEmpty()) return [];

        $companies = $companies->toArray();
        $result    = []; //定义最终数据
        foreach ($companies as $company) {
            $company['type']            = 'company';
            $company['company_id']      = $company['id'];
            $company['project_id']      = 0;
            $company['department_id']   = 0;
            $company['part_company_id'] = 0;
            $company['user_count']      = CompanyUser::query()->where('company_id', $company['id'])->count();
            //公司第一部分, 公司直属部门
            $treeDepartments = [];
            if (!empty($company['departments'])) {
                $treeDepartments = $this->needDepartment($company['departments'], $company['id'], 0, 0, true); //取得带结构树的departments
            }
            //公司第二部分, 项目下的参见单位和部门
            $projects = [];
            if (!empty($company['projects'])) {
                foreach ($company['projects'] as $project) {
                    $projects[] = $this->getProject($project, $company['id']);
                }
            }
            //两部分合并, 去除额外数据
            $company['children'] = array_merge($treeDepartments, $projects);
            unset($company['departments']);
            unset($company['projects']);
            $result[] = $company;
        }
        Cache::put('organize_id', 0);
        $result = $this->formatChildrenId($result);
        Cache::forget('organize_id');

        return $result;
    }

    /**
     * 组织架构最终数据将 id进行格式化，保证id唯一 （前端需要）
     */
    public function formatChildrenId($data)
    {
        foreach ($data as &$val) {
            $val['is_show_action'] = 0;
            $val['id'] = Cache::increment('organize_id');
            if (isset($val['children']) && !empty($val['children'])) {
                $val['children'] = $this->formatChildrenId($val['children']);
            }
        }

        return $data;
    }

    /**
     * 是否是项目下的参见单位用户
     */
    protected function isPartCompanyUser($partCompanyId = 0)
    {
        if (!$partCompanyId) {
            return false;
        }
        return PartCompanyUser::query()
            ->where('part_company_id', $partCompanyId)
            ->where('user_id', user_id())
            ->value('id');
    }

    /**
     * 是否属于部门员工
     */
    protected function isDepartmentUser($departmentId = 0)
    {
        if (!$departmentId) {
            return false;
        }
        return DepartmentUser::query()
            ->where('department_id', $departmentId)
            ->where('user_id', user_id())
            ->value('id');
    }

    /**
     * 获取单个项目下的参见单位和部门
     *
     */
    public function getProject($project, $companyId)
    {
        $project['type']            = 'project';
        $project['company_id']      = $companyId;
        $project['project_id']      = $project['id'];
        $project['department_id']   = 0;
        $project['part_company_id'] = 0;
        $project['user_count']      = ProjectUser::query()->where('project_id', $project['id'])->count();
        //项目第一部分，参建单位
        $partCompanies = [];
        if (!empty($project['part_companies'])) { //如果项目有参建单位
            $partCompanies = $project['part_companies'];
            foreach ($partCompanies as $thisKey1 => $partCompany) {
                //如果当前登录用户不是超管，不是公司管理员，并且也不是自己创建的，只能看自己所属单位，其余看不到
                if (!is_super_admin()
                    && !is_company_admin()
                    && !$this->isPartCompanyUser($partCompany['id'])
                    && (user_id() != $partCompany['creator_id'])
                ) {
                    unset($partCompanies[$thisKey1]);
                }
            }
            foreach ($partCompanies as &$val) {
                $val['part_company_type'] = $val['type'];
                $val['type']              = 'part_company';
                $val['company_id']        = $companyId;
                $val['project_id']        = $project['id'];
                $val['department_id']     = 0;
                $val['part_company_id']   = $val['id'];
                $val['user_count']        = PartCompanyUser::query()->where('part_company_id', $val['id'])->count();
                if ($val['departments']) {
                    $val['children'] = $this->needDepartment($val['departments'], $companyId, $project['id'], $val['id']);
                }
                unset($val['departments']);
            }
        }
        //项目第二部分，部门，项目的直属部门 project_id不为空，part_company_id为空
        $departments = [];
        if (!empty($project['departments'])) {
            $departments = $project['departments'];
            foreach ($departments as $thisKey2 => $department) {
                //如果当前登录用户不是超管，不是公司管理员，只能看自己所属单位，其余看不到
                if (!is_super_admin() && !is_company_admin() && !$this->isDepartmentUser($department['id'])) {
                    unset($departments[$thisKey2]);
                }
            }
            $departments = $this->needDepartment($departments, $companyId, $project['id'], 0);
        }
        //两部分合并, 去除额外数据
        $project['children'] = array_merge($partCompanies, $departments);
        unset($project['part_companies']);
        unset($project['departments']);

        return $project;
    }

    /**
     * 构造需要的部门字段数组
     */
    public function needDepartment($departments, $companyId, $projectId, $partCompanyId, $company = false)
    {
        $tempDepartments = [];
        foreach ($departments as &$val) {
            if ($company) { //直属部门，应排除属于 项目、参见单位的部门
                if ($val['project_id'] || $val['part_company_id']) {
                    unset($val);
                    continue;
                }
            }
            $temp['type']            = 'department';
            $temp['id']              = $val['id'];
            $temp['title']           = $val['title'];
            $temp['parent_id']       = $val['department_id'];
            $temp['company_id']      = $companyId;
            $temp['project_id']      = $projectId;
            $temp['department_id']   = $val['id'];
            $temp['part_company_id'] = $partCompanyId;
            $temp['user_count']      = DepartmentUser::query()->where('department_id', $val['id'])->count();
            $tempDepartments[]       = $temp;
        }

        return get_tree($tempDepartments); //获取全部部门和子部门
    }

    /**
     * 返回公司，部门，项目，参建单位其中一个下面的用户
     */
    public function getUsers($perPage, $companyId, $projectId = null, $departmentId = null, $partCompanyId = null, $keyword = null)
    {
        $users   = $this->companyService->users($companyId);
        $userIds = array_column($users, 'id'); //公司
        if ($projectId) { //项目
            $users   = $this->projectService->users($projectId);
            $userIds = array_column($users, 'id');
        }
        if ($partCompanyId) { //参建单位
            $users   = $this->partCompanyService->users($partCompanyId);
            $userIds = array_column($users, 'id');
        }
        if ($departmentId) { //部门
            $userIds = $this->departmentService->userIds($departmentId);
        }
        $list = User::query()->with([
                "roles",
                "companies",
                "departments",
                "projects",
                "partCompanies"
            ])
            ->leftJoin('company_user as cu', 'cu.user_id', '=', 'users.id')
            ->leftJoin('roles as r', 'cu.role_id', '=', 'r.id')
            ->where('cu.company_id', $companyId)
            ->whereIn('users.id', $userIds)
            ->when($keyword, function ($query) use ($keyword) {
                if (ctype_digit($keyword)) { //如果是纯数字组成，那就是手机号
                    $query->where('phone', 'like', "%{$keyword}%");
                } else {
                    $query->where('nickname', 'like', "%{$keyword}%");
                }
            })
            ->select(['users.id', 'users.phone', 'users.nickname', 'users.sex', 'users.no_hash_pwd', 'users.sex', 'r.title as role_name'])
            ->orderBy('users.id')
            ->paginate($perPage);

        if ($list->isEmpty()) return [];
        $list = $list->toArray();
        foreach ($list['data'] as &$val) {
            $userids[] = $val['id'];
            $val['status']  = 0;
            $val['is_edit'] = 1;
            if (!$val['role_name']) $val['role_name'] = '暂无角色';
            if ($val['role_name'] == '公司管理员') $val['is_edit'] = 0;
            foreach ($users as $user) {  //是否禁用， 注意这个值不是users表里面的status
                if ($val['id'] == $user['id']) {
                    $val['status'] = $user['status'];
                }
            }
        }

        return $this->removeNoUsedPageParams($list);
    }

    /**
     * 删除组织架构用户
     */
    public function delUser($userIds, $companyId, $projectId, $departmentId, $partCompanyId)
    {
        $userIds = to_array($userIds);
        foreach ($userIds as $userId) {
            if ($companyId) {
                CompanyUser::query()->where([
                    'user_id'    => $userId,
                    'company_id' => $companyId
                ])->delete();
            }
            if ($projectId) {
                ProjectUser::query()->where([
                    'user_id'    => $userId,
                    'project_id' => $projectId
                ])->delete();
            }
            if ($departmentId) {
                DepartmentUser::query()->where([
                    'user_id'       => $userId,
                    'department_id' => $departmentId
                ])->delete();
            }
            if ($partCompanyId) {
                PartCompanyUser::query()->where([
                    'user_id'         => $userId,
                    'part_company_id' => $partCompanyId
                ])->delete();
            }
            $userInfo = User::query()->find($userId);
            CommonService::addActionLog('删除组织架构用户', "被删除用户【{$userInfo->nickname}】");
        }
        return true;
    }

    /**
     * 更新内容标题名
     */
    public function editTitle($type, $id, $title)
    {
        $typeName = '部门';
        switch ($type) {
            case 'project':
                $instance = Project::query();
                $typeName = '项目';
                break;
            case 'part_company':
                $instance = PartCompany::query();
                $typeName = '参建单位';
                break;
            default:
                $instance = Department::query();
        }
        $info = $instance->find($id);
        CommonService::addActionLog("组织架构更新{$typeName}标题名", "数据ID:{$id}; 把【{$info->title}】修改为【{$title}】");

        return $info->update(['title' => $title]);
    }

    /**
     * 写入(公司)和用户的关联数据
     */
    public static function addCompanyUser($companyId, $userId)
    {
        $info = CompanyUser::query()->where([
            'user_id'    => $userId,
            'company_id' => $companyId
        ])->first();
        if (!$info) {
            $companyUser             = new CompanyUser();
            $companyUser->company_id = $companyId;
            $companyUser->user_id    = $userId;
            $companyUser->is_admin   = 0;
            $companyUser->creator_id = user_id();
            $companyUser->save();
        }
    }

    /**
     * 写入(项目)和用户的关联数据
     */
    public static function addProjectUser($projectId, $userId)
    {
        $info = ProjectUser::query()->where([
            'user_id'    => $userId,
            'project_id' => $projectId
        ])->first();
        if (!$info) {
            $projectUser             = new ProjectUser();
            $projectUser->project_id = $projectId;
            $projectUser->user_id    = $userId;
            $projectUser->creator_id = user_id();
            $projectUser->save();
        }
    }

    /**
     * 写入(参见单位)和用户的关联数据
     */
    public static function addPartCompanyUser($partCompanyId, $userId)
    {
        $info = PartCompanyUser::query()->where([
            'user_id'         => $userId,
            'part_company_id' => $partCompanyId
        ])->first();
        if (!$info) {
            $partCompanyUser                  = new PartCompanyUser();
            $partCompanyUser->part_company_id = $partCompanyId;
            $partCompanyUser->user_id         = $userId;
            $partCompanyUser->creator_id      = user_id();
            $partCompanyUser->save();
        }
    }

    /**
     * 写入(部门）和用户的关联数据
     */
    public static function addDepartmentUser($departmentId, $userId)
    {
        $info = DepartmentUser::query()->where([
            'user_id'       => $userId,
            'department_id' => $departmentId
        ])->first();
        if (!$info) {
            $departmentUser                = new DepartmentUser();
            $departmentUser->department_id = $departmentId;
            $departmentUser->user_id       = $userId;
            $departmentUser->creator_id    = user_id();
            $departmentUser->save();
        }
    }

    /**
     * 删除(项目)和用户的关联数据
     */
    public static function changeCompanyUser($companyId, $userId, $status)
    {
        //当前状态
        $nowStatus = CompanyUser::query()
            ->where('user_id', $userId)
            ->where('company_id', $companyId)
            ->value('status');

        $afterStatus = $nowStatus ? 0 : 1;

        CompanyUser::query() //禁用公司用户
        ->where('user_id', $userId)
            ->where('company_id', $companyId)
            ->update(['status' => $afterStatus]);

        $projectIds = Project::query()->where('company_id', $companyId)->pluck('id');
        $projectIds = $projectIds->isNotEmpty() ? $projectIds->toArray() : [];

        ProjectUser::query() //禁用项目下的参建单位关联
        ->where('user_id', $userId)
            ->whereIn('project_id', $projectIds)
            ->update(['status' => $status]);

        $partCompanyIds = PartCompany::query()->whereIn('project_id', $projectIds)->pluck('id');
        $partCompanyIds = $partCompanyIds->isNotEmpty() ? $partCompanyIds->toArray() : [];

        PartCompanyUser::query() //禁用项目下的参建单位关联
        ->where('user_id', $userId)
            ->whereIn('part_company_id', $partCompanyIds)
            ->update(['status' => $status]);
    }

    /**
     * 禁用项目和用户的关联数据
     */
    public static function changeProjectUser($projectId, $userId, $status)
    {
        ProjectUser::query()
            ->where('user_id', $userId)
            ->where('project_id', $projectId)
            ->update(['status' => $status]);

        $partCompanyIds = PartCompany::query()->where('project_id', $projectId)->pluck('id');
        $partCompanyIds = $partCompanyIds->isNotEmpty() ? $partCompanyIds->toArray() : [];

        PartCompanyUser::query() //禁用项目下的参建单位关联
        ->where('user_id', $userId)
            ->whereIn('part_company_id', $partCompanyIds)
            ->update(['status' => $status]);
    }

    /**
     * 禁用项目和用户的关联数据
     */
    public static function changePartCompanyUser($partCompanyId, $userId, $status)
    {
        PartCompanyUser::query() //禁用项目下的参建单位关联
        ->where('user_id', $userId)
            ->where('part_company_id', $partCompanyId)
            ->update(['status' => $status]);
    }

}
